/**
 * dart 面向对象
 * 
 * dart 是一种基于类和 mixin 继承机制的面向对象的语言
 * 只要希望可以反复创建同一类型的相同结构的多个对象时，都可以通过类(class)反复创建
 * 每个对象都是一个类的实例，所有的类都继承自Object
 * 基于 Mixin 继承意味着每个类（Object除外）都只有一个超类，一个类中的代码可以在其他多个继承类中重复使用
 * 
 * 如何定义一个类:
 * 
 * class 类名 {
 *    数据类型 属性名 = 初始值;
 *    
 *    构造函数(数据类型 形参1, 数据类型 形参2, ...) { // 构造函数名必须和类名相同
 *        this.属性名 = 形参;
 *        this.xxx = xxx;
 *        ...
 *    }
 * 
 *    返回值类型 方法名(参数列表) {
 *        方法体;
 *        return 返回值;
 *    }
 * }
 * 
 * 创建一个对象：
 * 
 *  var 变量名 = new 类名(); // new 可以省略
 * 
 * 构造函数简写：
 * 
 *  构造函数(this.属性名, this.属性名, ...);
 * 
 *  构造函数(形参1, 形参2, ...):
 *    属性名 = 形参,
 *    xxx = 形参;
 * 
 * 获得一个对象的运行时类名： 对象.runtimeType;
 * 
 * 命名构造函数
 * 
 *  如果一种类型的对象，可通过多种途径创建时，就可在标准构造函数之外再定义其他命名构造函数
 *  如何定义:
 *    类型名.别名(形参) { ... }
 *  创建对象：
 *    var 变量名 = 类型名.别名(实参值);
 *  简写：如果命名构造函数只是为了给将来的新对象每个属性赋值，也可以使用初始化属性列表的方式简写
 *    类型名.别名(形参列表): 属性名1 = 形参1, 属性名2 = 形参2, ...;
 * 
 * 继承和扩展
 * 
 *  当一个子类型，想拥有和父类型一致的属性结构和功能时，子类型就可继承父类型
 * 
 *  class 子类型 extends 父类型 {
 *    子类型自己的属性;
 *    子类型构造函数(参数列表): super(参数列表) {
 *      给子类型自有属性赋值;
 *    }
 *  }
 * 
 *  也可用初始化列表来简写：
 *    子类型构造函数(参数列表):
 *      子类型属性 = 赋值,
 *      super(参数列表);
 * 
 * 抽象类和抽象方法
 *  如果有些父类型，虽然知道子类型必须具有什么功能，但是，因为不同子类型实现功能的方法各不相同，
 *  父类型无法统一规定，就可以定义抽象类型
 * 
 *  在抽象父类型中，可以包含抽象方法，也就是只有方法签名，没有方法实现的特殊空方法
 * 
 *  结果：子类型继承抽象父类型，就必须按抽象父类型的要求，实现所有抽象方法。
 * 
 */